/**
 * 百度语音合成（TTS）HTTP服务
 * 使用百度云语音合成 REST API
 * 文档：https://ai.baidu.com/ai-doc/SPEECH/Qk38y8lrl
 */

import { BAIDU_API_KEY, BAIDU_SECRET_KEY } from '@env';
import { Platform } from 'react-native';

class BaiduTtsService {
  constructor() {
    this.currentSound = null;
    this.accessToken = null;
    this.tokenExpireTime = 0;
    this.audioPlayer = null;

    // 延迟加载 Sound 以避免初始化问题
    this.Sound = null;

    // TTS缓存（相同文本直接复用）
    this.ttsCache = new Map(); // key: text+options, value: audioBuffer
    this.maxCacheSize = 20; // 最多缓存20个音频

    // 流式播放队列（按索引排序）
    this.playQueue = new Map(); // key: index, value: {path, index, total}
    this.isPlaying = false;
    this.currentQueueSound = null;
    this.nextPlayIndex = 0; // 下一个应该播放的段落索引
  }

  /**
   * 初始化 Sound 库
   */
  initSound() {
    if (!this.Sound) {
      try {
        const Sound = require('react-native-sound');
        Sound.setCategory('Playback');
        this.Sound = Sound;
      } catch (error) { }
    }
    return this.Sound;
  }

  /**
   * 添加到缓存
   */
  addToCache(key, value) {
    // LRU缓存：如果超过最大缓存数，删除最旧的
    if (this.ttsCache.size >= this.maxCacheSize) {
      const firstKey = this.ttsCache.keys().next().value;
      this.ttsCache.delete(firstKey);
    }
    this.ttsCache.set(key, value);
  }

  /**
   * 清空缓存
   */
  clearCache() {
    this.ttsCache.clear();
  }

  /**
   * 预加载 Access Token（应用启动时调用，避免首次使用延迟）
   */
  async preloadAccessToken() {
    try {
      await this.getAccessToken();
    } catch (error) {
      console.warn('⚠️ 预加载百度TTS Token失败:', error.message);
    }
  }

  /**
   * 获取 Access Token
   * Token 有效期 30 天，缓存后重复使用
   */
  async getAccessToken() {
    // 如果 token 还未过期，直接返回
    if (this.accessToken && Date.now() < this.tokenExpireTime) {
      return this.accessToken;
    }

    try {
      // 调试：检查环境变量是否正确读取

      if (!BAIDU_API_KEY || !BAIDU_SECRET_KEY) {
        throw new Error(
          '百度 API 密钥未配置！请检查 .env 文件中的 BAIDU_API_KEY 和 BAIDU_SECRET_KEY',
        );
      }

      const url = `https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${BAIDU_API_KEY}&client_secret=${BAIDU_SECRET_KEY}`;

      const response = await fetch(url, { method: 'POST' });
      const data = await response.json();

      if (data.error) {
        throw new Error(`获取Token失败: ${data.error_description}`);
      }

      this.accessToken = data.access_token;
      // Token 有效期 30 天，提前 1 天刷新
      this.tokenExpireTime = Date.now() + 29 * 24 * 60 * 60 * 1000;

      return this.accessToken;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 长文本TTS合成（支持10万字以内）
   * @param {string} text - 要合成的文本
   * @param {Object} options - 合成参数
   * @returns {Promise<ArrayBuffer>} 音频数据
   */
  async synthesizeLongText(text, options = {}) {
    try {
      const token = await this.getAccessToken();

      // 步骤1: 提交长文本合成任务
      const createUrl = 'https://aip.baidubce.com/rpc/2.0/tts/v1/create';
      const createParams = {
        access_token: token,
      };

      const createBody = {
        text: text,
        format: 'mp3-16k',
        voice: options.voiceName || '4', // 默认情感女声
        lang: 'zh',
        speed: parseInt(options.speed || '5'),
        pitch: parseInt(options.pitch || '5'),
        volume: parseInt(options.volume || '9'),
        enable_subtitle: 0,
      };

      const createResponse = await fetch(
        `${createUrl}?${new URLSearchParams(createParams).toString()}`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(createBody),
        }
      );

      const createResult = await createResponse.json();

      if (createResult.error_code) {
        throw new Error(`提交TTS任务失败: ${createResult.error_msg}`);
      }

      const taskId = createResult.task_id;

      // 步骤2: 轮询任务状态
      const queryUrl = 'https://aip.baidubce.com/rpc/2.0/tts/v1/query';
      let audioData = null;
      let attempts = 0;
      const maxAttempts = 60; // 最多尝试60次（2分钟）
      const queryInterval = 2000; // 每2秒查询一次（减少查询频率）


      while (attempts < maxAttempts) {
        await new Promise(resolve => setTimeout(resolve, queryInterval));
        attempts++;

        const queryResponse = await fetch(
          `${queryUrl}?${new URLSearchParams({ access_token: token }).toString()}`,
          {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({ task_ids: [taskId] }),
          }
        );

        // 检查响应状态
        if (!queryResponse.ok) {
          const errorText = await queryResponse.text();
          console.error('❌ 查询响应错误:', queryResponse.status, errorText);
          throw new Error(`查询TTS任务HTTP错误: ${queryResponse.status}`);
        }

        // 先获取原始响应文本
        const responseText = await queryResponse.text();

        let queryResult;
        try {
          queryResult = JSON.parse(responseText);
        } catch (parseError) {
          console.error('❌ JSON解析失败，原始响应:', responseText);
          throw new Error(`查询TTS任务失败: invalid json - ${responseText.substring(0, 100)}`);
        }

        if (queryResult.error_code) {
          throw new Error(`查询TTS任务失败: ${queryResult.error_msg}`);
        }

        // 从 tasks_info 数组中获取任务状态
        const taskInfo = queryResult.tasks_info?.[0];
        if (!taskInfo) {
          throw new Error('查询TTS任务失败: 未找到任务信息');
        }


        if (taskInfo.task_status === 'Success') {
          // 任务完成，下载音频
          const audioUrl = taskInfo.task_result.speech_url;

          const audioResponse = await fetch(audioUrl);
          audioData = await audioResponse.arrayBuffer();

          break;
        } else if (taskInfo.task_status === 'Failed') {
          throw new Error('TTS合成失败');
        }
        // 否则继续等待
      }

      if (!audioData) {
        throw new Error('TTS合成超时');
      }

      return audioData;
    } catch (error) {
      console.error('❌ 长文本TTS失败:', error);
      throw error;
    }
  }

  /**
   * 短文本合成语音（使用POST方法，推荐）
   * @param {string} text - 要合成的文本
   * @param {Object} options - 合成参数
   * @returns {Promise<ArrayBuffer>} 音频数据
   */
  async synthesize(text, options = {}) {
    try {
      // 支持外部传入AbortSignal用于取消请求
      const fetchSignal = options && options.fetchSignal;

      // 构建用于缓存的关键参数，剔除不可序列化的signal
      const { fetchSignal: _omit, ...cacheableOptions } = options || {};

      // 检查缓存
      const cacheKey = `${text}_${JSON.stringify(cacheableOptions)}`;
      if (this.ttsCache.has(cacheKey)) {
        return this.ttsCache.get(cacheKey);
      }

      const token = await this.getAccessToken();

      // 对tex参数进行2次urlencode（百度推荐，避免特殊字符问题）
      const texEncoded = encodeURIComponent(encodeURIComponent(text));

      // 手动构建body，因为tex需要2次编码
      const bodyParams = [
        `tex=${texEncoded}`,
        `tok=${token}`,
        `cuid=BellaTravel`,
        `ctp=1`,
        `lan=zh`,
        `spd=${options.speed || '5'}`,
        `pit=${options.pitch || '5'}`,
        `vol=${options.volume || '9'}`,
        `per=${options.voiceName || '0'}`,
        `aue=3`
      ].join('&');


      // 创建超时控制（15秒）
      const timeoutController = new AbortController();
      const timeoutId = setTimeout(() => timeoutController.abort(), 15000);

      try {
        const response = await fetch('https://tsn.baidu.com/text2audio', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': '*/*',
          },
          body: bodyParams,
          signal: fetchSignal || timeoutController.signal,
        });

        clearTimeout(timeoutId);

        if (!response.ok) {
          throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        // 检查响应类型
        const contentType = response.headers.get('content-type');

        if (contentType && contentType.includes('application/json')) {
          // 如果返回的是 JSON，说明出错了
          const errorData = await response.json();
          throw new Error(`百度TTS错误: ${errorData.err_msg || '未知错误'}`);
        }

        // 获取音频数据
        const audioData = await response.arrayBuffer();

        if (audioData.byteLength === 0) {
          throw new Error('未获取到音频数据');
        }

        // 缓存音频数据
        this.addToCache(cacheKey, audioData);

        return audioData;
      } catch (fetchError) {
        clearTimeout(timeoutId);
        throw fetchError;
      }

    } catch (error) {
      // 区分不同的错误类型
      if (error.name === 'AbortError') {
        console.warn('⚠️ TTS请求被取消或超时');
        throw new Error('TTS请求超时，请检查网络连接');
      }
      console.error('❌ 短文本TTS失败:', error.message || error);
      throw error;
    }
  }

  /**
   * 智能分段文本（在句子边界处分割）
   * @param {string} text - 要分段的文本
   * @param {number} maxLength - 每段最大长度（默认400字）
   * @returns {Array<string>} 文本段数组
   */
  splitTextIntoSegments(text, maxLength = 400) {
    const segments = [];
    const sentences = text.match(/[^。！？；.!?;]+[。！？；.!?;]*/g) || [text];

    let currentSegment = '';

    for (const sentence of sentences) {
      // 如果单句就超过maxLength，直接作为一段
      if (sentence.length > maxLength) {
        if (currentSegment) {
          segments.push(currentSegment.trim());
          currentSegment = '';
        }
        segments.push(sentence.trim());
        continue;
      }

      // 如果加上当前句子会超长，先保存已有的段
      if (currentSegment.length + sentence.length > maxLength) {
        if (currentSegment) {
          segments.push(currentSegment.trim());
        }
        currentSegment = sentence;
      } else {
        currentSegment += sentence;
      }
    }

    // 保存最后一段
    if (currentSegment) {
      segments.push(currentSegment.trim());
    }

    return segments;
  }

  /**
   * 限制并发数的Promise执行器
   * @param {Array} tasks - 任务数组，每个任务是一个返回Promise的函数
   * @param {number} limit - 最大并发数
   * @returns {Promise<Array>} 所有任务结果
   */
  async limitConcurrency(tasks, limit = 5) {
    const results = [];
    const executing = [];

    for (const [index, task] of tasks.entries()) {
      const promise = Promise.resolve().then(() => task()).then(result => {
        results[index] = result;
        return result;
      });

      results.push(promise);

      if (limit <= tasks.length) {
        const executing_promise = promise.then(() => {
          executing.splice(executing.indexOf(executing_promise), 1);
        });
        executing.push(executing_promise);

        if (executing.length >= limit) {
          await Promise.race(executing);
        }
      }
    }

    await Promise.all(results);
    return results;
  }

  /**
   * 分段合成音频并合并（带并发控制）
   * @param {string} text - 要合成的文本
   * @param {Object} options - 合成参数
   * @returns {Promise<ArrayBuffer>} 合并后的音频数据
   */
  async synthesizeInSegments(text, options = {}) {
    try {
      const startTime = Date.now();

      // 分段（每段510字，接近API上限512字）
      const segments = this.splitTextIntoSegments(text, 510);

      // 🚀 并发合成所有段落（最多同时5个请求）

      // 创建任务数组
      const tasks = segments.map((segment, index) => {
        return async () => {
          try {
            const audioData = await this.synthesize(segment, options);
            return audioData;
          } catch (error) {
            console.error(`❌ [${index + 1}/${segments.length}] 合成失败:`, error.message);
            throw error;
          }
        };
      });

      // 使用并发控制执行
      const audioBuffers = await this.limitConcurrency(tasks, 5);

      const synthesizeTime = ((Date.now() - startTime) / 1000).toFixed(1);

      // 合并音频数据（简单拼接，适用于同格式音频）
      const totalLength = audioBuffers.reduce((sum, buffer) => sum + buffer.byteLength, 0);
      const mergedBuffer = new Uint8Array(totalLength);
      let offset = 0;

      for (const buffer of audioBuffers) {
        mergedBuffer.set(new Uint8Array(buffer), offset);
        offset += buffer.byteLength;
      }

      const totalTime = ((Date.now() - startTime) / 1000).toFixed(1);
      return mergedBuffer.buffer;

    } catch (error) {
      console.error('❌ 分段合成失败:', error);
      throw error;
    }
  }

  /**
   * 流式分段合成并播放（第一段完成立即播放，后续无缝衔接）
   * @param {string} text - 要合成的文本
   * @param {Object} options - 合成参数
   * @returns {Promise<void>}
   */
  async synthesizeInSegmentsStreaming(text, options = {}) {
    try {
      const startTime = Date.now();

      // 分段
      const segments = this.splitTextIntoSegments(text, 510);

      // 清空播放队列
      this.playQueue.clear();
      this.isPlaying = false;
      this.nextPlayIndex = 0;

      // 创建任务数组，但不使用并发控制（按顺序合成）
      const segmentPromises = [];

      for (let i = 0; i < segments.length; i++) {
        const segment = segments[i];
        const segmentIndex = i;

        // 每段合成完成后立即添加到队列
        const promise = this.synthesize(segment, options)
          .then(async (audioData) => {

            // 添加到播放队列
            await this.addToPlayQueue(audioData, segmentIndex, segments.length);

            return audioData;
          })
          .catch(error => {
            console.error(`❌ [${segmentIndex + 1}/${segments.length}] 合成失败:`, error.message);
            throw error;
          });

        segmentPromises.push(promise);

        // 第一段：不等待，立即开始合成下一段
        // 后续段：稍微错开，避免同时发起太多请求
        if (i < segments.length - 1) {
          await new Promise(resolve => setTimeout(resolve, 100));
        }
      }

      // 等待所有段落合成完成
      await Promise.all(segmentPromises);

      const totalTime = ((Date.now() - startTime) / 1000).toFixed(1);

    } catch (error) {
      console.error('❌ 流式分段合成失败:', error);
      throw error;
    }
  }

  /**
   * 添加到播放队列并自动播放
   * @param {ArrayBuffer} audioData - 音频数据
   * @param {number} index - 段落索引
   * @param {number} total - 总段落数
   */
  async addToPlayQueue(audioData, index, total) {
    try {
      const RNFS = require('react-native-fs');
      const SoundClass = this.initSound();

      // 保存到临时文件
      const uint8Array = new Uint8Array(audioData);
      let binaryString = '';
      for (let i = 0; i < uint8Array.length; i++) {
        binaryString += String.fromCharCode(uint8Array[i]);
      }
      const base64Audio = btoa(binaryString);

      const audioPath = `${RNFS.CachesDirectoryPath}/tts_stream_${index}_${Date.now()}.mp3`;
      await RNFS.writeFile(audioPath, base64Audio, 'base64');

      // 添加到队列（使用Map按索引存储）
      this.playQueue.set(index, { path: audioPath, index, total });

      // 如果当前没有在播放，且这是第一段（index=0），立即开始播放
      if (!this.isPlaying && index === 0) {
        this.playNextInQueue(total);
      } else if (this.isPlaying && index === this.nextPlayIndex) {
        // 如果正在播放，且当前合成完的正好是下一段需要的
      }

    } catch (error) {
      console.error('❌ 添加到播放队列失败:', error);
      throw error;
    }
  }

  /**
   * 播放队列中的下一段音频（按索引顺序）
   */
  playNextInQueue(total) {
    // 检查下一段是否已经准备好
    if (!this.playQueue.has(this.nextPlayIndex)) {
      this.isPlaying = false;
      return;
    }

    const nextItem = this.playQueue.get(this.nextPlayIndex);
    this.playQueue.delete(this.nextPlayIndex);

    const { path, index } = nextItem;
    const currentTotal = total || nextItem.total;

    this.isPlaying = true;

    const SoundClass = this.initSound();

    this.currentQueueSound = new SoundClass(path, '', (error) => {
      if (error) {
        console.error(`❌ [${index + 1}/${currentTotal}] 加载失败:`, error);
        // 继续播放下一段
        this.nextPlayIndex++;
        this.playNextInQueue(currentTotal);
        return;
      }

      // 播放当前段
      this.currentQueueSound.play((success) => {
        if (success) {
        } else {
        }

        // 清理资源
        if (this.currentQueueSound) {
          this.currentQueueSound.release();
          this.currentQueueSound = null;
        }

        // 删除临时文件
        const RNFS = require('react-native-fs');
        RNFS.unlink(path).catch(() => { });

        // 移动到下一段
        this.nextPlayIndex++;

        // 检查是否还有更多段落
        if (this.nextPlayIndex < currentTotal) {
          this.playNextInQueue(currentTotal);
        } else {
          this.isPlaying = false;
          this.nextPlayIndex = 0;
        }
      });
    });
  }

  /**
   * 播放音频（ArrayBuffer）
   * @param {ArrayBuffer} audioData - 音频数据
   * @returns {Promise<void>}
   */
  async playAudioBuffer(audioData) {
    try {
      // 将 ArrayBuffer 转换为 base64
      const uint8Array = new Uint8Array(audioData);
      let binaryString = '';
      for (let i = 0; i < uint8Array.length; i++) {
        binaryString += String.fromCharCode(uint8Array[i]);
      }
      const base64Audio = btoa(binaryString);

      const RNFS = require('react-native-fs');
      const audioPath = `${RNFS.CachesDirectoryPath
        }/baidu_tts_${Date.now()}.mp3`;

      // 写入文件
      await RNFS.writeFile(audioPath, base64Audio, 'base64');

      // 初始化 Sound 库
      const SoundClass = this.initSound();

      // 使用 Promise 包装 Sound 播放
      return new Promise((resolve, reject) => {
        // 使用文件路径播放（空字符串表示绝对路径）
        this.currentSound = new SoundClass(audioPath, '', error => {
          if (error) {
            // 删除失败的文件
            RNFS.unlink(audioPath).catch(() => { });
            reject(error);
            return;
          }

          this.currentSound.play(success => {
            if (success) {
            } else {
            }

            // 释放资源
            if (this.currentSound) {
              this.currentSound.release();
              this.currentSound = null;
            }

            // 删除临时文件
            RNFS.unlink(audioPath).catch(() => { });

            if (success) {
              resolve();
            } else {
              reject(new Error('播放失败'));
            }
          });
        });
      });
    } catch (error) {
      throw error;
    }
  }

  /**
   * 合成并播放（一步到位）
   * 自动选择短文本或长文本接口
   * @param {string} text - 要合成的文本
   * @param {Object} options - 合成参数
   */
  async speak(text, options = {}) {
    try {
      // 停止当前播放
      this.stop();

      // 根据文本长度选择合适的接口
      // 短文本API：建议不超过120字，最长支持1024 GBK字节（约512个汉字）
      // 长文本API：支持10万字以内，但处理速度较慢
      const textLength = text.length;
      let audioData;

      // 新策略：优先使用分段并发合成（最快），降级使用长文本API
      // 短文本API最长支持1024字节（约512汉字），为安全起见单段设为510字
      if (textLength > 510) {
        try {
          // 优先使用分段并发合成（最快，3-4秒）
          audioData = await this.synthesizeInSegments(text, options);
        } catch (error) {
          console.warn('⚠️ 分段合成失败，尝试使用长文本API:', error.message);
          try {
            // 降级方案1: 使用长文本API（速度慢但支持长文本）
            audioData = await this.synthesizeLongText(text, options);
          } catch (longTextError) {
            console.warn('⚠️ 长文本API也失败，仅合成前510字:', longTextError.message);
            // 降级方案2: 只合成前510字
            audioData = await this.synthesize(text.substring(0, 510), options);
          }
        }
      } else {
        audioData = await this.synthesize(text, options);
      }

      // 播放音频
      await this.playAudioBuffer(audioData);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 暂停播放
   */
  pause() {
    if (this.currentQueueSound) {
      try {
        this.currentQueueSound.pause();
        this.isPaused = true;
      } catch (error) {
        console.error('⚠️ 暂停流式TTS失败:', error);
      }
    } else if (this.currentSound) {
      try {
        this.currentSound.pause();
        this.isPaused = true;
      } catch (error) {
        console.error('⚠️ 暂停TTS失败:', error);
      }
    }
  }

  /**
   * 恢复播放
   */
  resume() {
    if (this.currentQueueSound) {
      try {
        this.currentQueueSound.play();
        this.isPaused = false;
      } catch (error) {
        console.error('⚠️ 恢复流式TTS失败:', error);
      }
    } else if (this.currentSound) {
      try {
        this.currentSound.play();
        this.isPaused = false;
      } catch (error) {
        console.error('⚠️ 恢复TTS失败:', error);
      }
    }
  }

  /**
   * 获取当前播放位置
   */
  getCurrentTime(callback) {
    if (this.currentQueueSound) {
      this.currentQueueSound.getCurrentTime(callback);
    } else if (this.currentSound) {
      this.currentSound.getCurrentTime(callback);
    } else {
      callback(0);
    }
  }

  /**
   * 获取音频时长
   */
  getDuration() {
    if (this.currentQueueSound) {
      return this.currentQueueSound.getDuration();
    } else if (this.currentSound) {
      return this.currentSound.getDuration();
    }
    return 0;
  }

  /**
   * 设置播放位置
   */
  setCurrentTime(time) {
    if (this.currentQueueSound) {
      try {
        this.currentQueueSound.setCurrentTime(time);
      } catch (error) {
        console.error('⚠️ 设置流式TTS播放位置失败:', error);
      }
    } else if (this.currentSound) {
      try {
        this.currentSound.setCurrentTime(time);
      } catch (error) {
        console.error('⚠️ 设置TTS播放位置失败:', error);
      }
    }
  }

  /**
   * 停止播放（包括流式播放）
   */
  stop() {
    return new Promise((resolve) => {
      // 停止流式播放队列
      if (this.currentQueueSound) {
        try {
          this.currentQueueSound.stop(() => {
            if (this.currentQueueSound) {
              this.currentQueueSound.release();
              this.currentQueueSound = null;
            }
          });
        } catch (error) {
          console.error('⚠️ 停止流式TTS失败:', error);
          this.currentQueueSound = null;
        }
      }

      // 清空播放队列
      this.playQueue.clear();
      this.isPlaying = false;
      this.isPaused = false;
      this.nextPlayIndex = 0;

      // 停止普通播放
      if (this.currentSound) {
        try {
          this.currentSound.stop(() => {
            if (this.currentSound) {
              this.currentSound.release();
              this.currentSound = null;
            }
            resolve();
          });
        } catch (error) {
          // 出错也要 resolve，避免卡住
          if (this.currentSound) {
            this.currentSound = null;
          }
          resolve();
        }
      } else {
        resolve();
      }
    });
  }

  /**
   * 清理资源
   */
  async cleanup() {
    await this.stop();
    this.accessToken = null;
    this.tokenExpireTime = 0;
  }
}

export default new BaiduTtsService();
